/*
 * @Author: 邱狮杰
 * @Date: 2021-07-16 21:45:47
 * @LastEditTime: 2021-07-16 22:08:43
 * @FilePath: /babelPluginTemplate/src/entry.ts
 * @Description: entry
 */
import type { BabelAPI } from '@babel/helper-plugin-utils'
import { declare } from '@babel/helper-plugin-utils'
import { generateMd } from './core/generateMd'
import { ClassTypes, methodsInfoTypes } from './types/class'
import { FunctionTypes } from './types/func'
import { Options } from './types/ops'
import { generateClassMethod, generateClassProperty } from './utils/class'
import { preseComment } from './utils/common'
import { getFuncParamsList } from './utils/func'
import { resolveReturnType, resolveType } from './utils/type'

// @ts-ignore
export default declare((api: BabelAPI, _option: any, _dirName: string) => {
  api.assertVersion(7)
  return {
    pre(file) {
      // @ts-ignore
      file.set('docs', [])
      // @ts-ignore
      file.set('options', {} as Options)
    },
    visitor: {
      FunctionDeclaration(path, ops) {
        // @ts-ignore
        const docs = ops.file.get('docs')
        // @ts-ignore
        ops.file.set('options', ops.opts)
        const name = path.get('id').toString()
        // 排除以下划线开头的函数
        if (name[0] === '_') {
          path.skip()
          return
        }

        const funcInfo: FunctionTypes = {
          type: 'function',
          name,
          params: getFuncParamsList(path),
          // @ts-ignore
          return: resolveReturnType(path.get('returnType').getTypeAnnotation()),
        }
        if (path.node.leadingComments && path.node.leadingComments?.[0]?.value) {
          funcInfo.doc = preseComment(path.node.leadingComments?.[0]?.value)
        }
        docs.push(funcInfo as FunctionTypes)
        // @ts-ignore
        ops.file.set('docs', docs)
      },
      ClassDeclaration(path, ops) {
        // @ts-ignore
        const docs = ops.file.get('docs')
        // @ts-ignore
        ops.file.set('options', ops.opts)
        const name = path.get('id').toString()
        const classInfo = {
          type: 'class',
          name,
          constructorInfo: {},
          methodsInfo: [],
          propertiesInfo: [],
          // doc: [],
        } as unknown as ClassTypes
        generateClassProperty(content => {
          classInfo.propertiesInfo.push(content)
        }, path)
        generateClassMethod((constuctInfo: ClassTypes['constructorInfo'] | null, methodInfo: methodsInfoTypes | null) => {
          if (constuctInfo) classInfo.constructorInfo = constuctInfo
          if (methodInfo) classInfo.methodsInfo.push(methodInfo)
        }, path)
        console.log(path.node)
        if (path.node.leadingComments) {
          const docResult = preseComment(path.node.leadingComments[0].value)
          if (docResult) classInfo.doc = docResult
        }
        docs.push(classInfo)
        // @ts-ignore
        ops.file.set('docs', docs)
      },
    },
    post(file) {
      // @ts-ignore
      const content = file.get('docs')
      // @ts-ignore
      const ops = file.get('options')
      new generateMd.GenerateMd(content, ops).run()
    },
  }
})
